from flask import session, request,current_app
import hashlib
import re
import psutil
from sqlalchemy import func
from datetime import timedelta
from flask_mail import Message
from html import unescape
import redis
from app.models import *
import oss2
from oss2.models import BucketReferer
from functools import wraps
from flask_sitemap import Sitemap, sitemap_page_needed
import json
from app import config
from app.config import Config
from app import celery,mail,db,cache,sitemap
from app.views.utils import get_country_translate,get_country_list
# 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
auth = oss2.Auth(Config.AccessKey, Config.AccessSession)
# Endpoint以杭州为例，其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, Config.OssURL, Config.BucketName)
bucket.put_bucket_referer(BucketReferer(True, []))


# 自定义缓存名
def make_cache_key():
    """Dynamic creation the request url.自定义缓存名"""
    if(len(request.path)>1):
        path = request.path+'/'
    else:
        path=request.path
    h1 = hashlib.md5()
    item_dict=[item for item in request.args.items()]
    if request.form:
        item_dict.extend([item for item in request.form.items()])
    if request.get_data(as_text=True):
        item_dict.extend([item for item in json.loads(request.get_data(as_text=True)).items()])
    if 'admin' in path:
        item_dict.extend([str(item) for item in session.values()])
    h1.update(str(frozenset(item_dict)).encode())
    return 'zimu_' + path + h1.hexdigest()

@sitemap_page_needed.connect
def create_page(app, page, urlset):
    cache[page] = sitemap.render_page(urlset=urlset)

def load_page(fn):
    @wraps(fn)
    def loader(*args, **kwargs):
        page = kwargs.get('page')
        data = cache.get(page)
        return data if data else fn(*args, **kwargs)
    return loader

#简单html文本转纯text
def html_to_plain_text(html):
    text = re.sub('<head.*?>.*?</head>', '\n', html, flags=re.M | re.S | re.I)
    text = re.sub('<a\s.*?>', ' HYPERLINK ', text, flags=re.M | re.S | re.I)
    text = re.sub('<.*?>', '\n', text, flags=re.M | re.S)
    text = re.sub(r'(\s*\n)+', '\n', text, flags=re.M | re.S)
    return unescape(text)

# 邮件发送监控
def go_send_email_test(emailTo,nickname,token):
    msg = Message( '【请查收】子沐博客激活邮件', sender=current_app.config['MAIL_DEFAULT_SENDER'], recipients=[emailTo])
    href = f"{current_app.config['DOMAIN']}/checktoken?token={token}"
    msg.html = f'<h1>{nickname},欢迎加入子沐博客<h1><br/><a href="{href}">{href}</a>'
    try:
        with current_app.app_context():
            mail.send(msg)
            print("邮件发送成功")
    except Exception as e:
        print(str(e))

# cpu、内存监控
def getMemCpu():
     data = psutil.virtual_memory()
     total = round(data.total/1024/1024/1024,2) #总内存,单位为gb
     free = round(data.available/1024/1024/1024,2) #空余内存
     memory = int(round(data.percent))
     cpu = psutil.cpu_percent(interval=1)
     return {'memory':memory,'cpu':cpu,'total':total,'free':free}

# 今日流量趋势(小时)
def today_is_traffic_trends():
    # 今日流量趋势(小时)
    NOW = datetime.utcnow()
    # pv
    today_is_traffic_trends_pv = db.session.query(func.hour(Log.createtime), func.count(Log.id)).filter(
        db.cast(Log.createtime, db.DATE) == NOW.date()).group_by(
        func.hour(Log.createtime)).all()
    # uv
    today_is_traffic_trends_uv = db.session.query(func.hour(Log.createtime), func.count(Log.id)).distinct().filter(
        db.cast(Log.createtime, db.DATE) == NOW.date()).group_by(func.hour(Log.createtime), Log.ip).all()
    pv_list = []  # pv列表
    uv_list = []  # uv列表
    hour_list = []  # 时间列表
    for pv, uv in zip(today_is_traffic_trends_pv, today_is_traffic_trends_uv):
        hour_list.append('%2d:00' % pv[0])
        pv_list.append(pv[1])
        uv_list.append(uv[1])
    return {'label': hour_list, 'pv': pv_list, 'uv': uv_list}

# 历史流量趋势(小时)
def history_is_traffic_trends():
    # pv
    today_is_traffic_trends_pv = db.session.query(Log.createtime, func.count(Log.id)).order_by(Log.createtime).group_by(Log.createtime).all()
    # uv
    today_is_traffic_trends_uv = db.session.query(Log.createtime, func.count(Log.id)).distinct().order_by(Log.createtime).group_by(Log.createtime,Log.ip).all()
    pv_list = []  # pv列表
    uv_list = []  # uv列表
    hour_list = []  # 时间列表
    for pv, uv in zip(today_is_traffic_trends_pv, today_is_traffic_trends_uv):
        hour_list.append(pv[0].strftime('%Y-%m-%d'))
        pv_list.append(pv[1])
        uv_list.append(uv[1])
    return {'label': hour_list, 'pv': pv_list, 'uv': uv_list}

def visitor_browser_distribution():
    # 访客浏览器分布
    visitor_browser_distribution_list = db.session.query(Log.browser, func.count(Log.id)).group_by(Log.browser).all()
    vbd_list = []  # 浏览器数据
    vbd_data = []  # 浏览器名字列表
    for brower, data in visitor_browser_distribution_list:
        vbd_data.append(brower)
        vbd_list.append({'name': brower, 'value': data})
    return {'label': vbd_data, 'data': vbd_list}

def system_distribution():
    # 操作系统分布
    system_distribution_list = db.session.query(Log.platform, func.count(Log.id)).group_by(Log.platform).all()
    system_list = []  # 浏览器数据
    system_data = []  # 浏览器名字列表
    for system, data in system_distribution_list:
        system_data.append(system)
        system_list.append({'name': system, 'value': data})
    return {'label': system_data, 'data': system_list}

def ipaddress_distribution():
    # 国家分布
    ipaddress_distribution_list = db.session.query(Log.country, func.count(Log.id)).filter(Log.country.isnot(None)).group_by(Log.country).all()
    get_dict=get_country_list()
    country_translate=get_country_translate()
    for ipaddress, data in ipaddress_distribution_list:
        ipaddress=ipaddress.replace('美国', '美利坚合众国')
        country=country_translate.get(ipaddress)
        if country in get_dict:
            get_dict[country]=data
        else:
            continue
    ipaddress_distribution_data=[{'name':k,'value':v} for k,v in get_dict.items()]# 城市分布数据
    return {'data': ipaddress_distribution_data}

def top5_ip_list():
    # Top5 ip排行榜
    log_list=db.session.query(Log.ip,func.count(1).label("count_Id")).order_by(func.count(1).desc()).group_by(Log.ip).limit(5).offset(0).all()
    ip_label=[]
    ip_data=[]
    for item in log_list:
        ip_label.append(item[0])
        ip_data.append(item[1])
    return {'label':ip_label,'data':ip_data}


# model对象转json
def serialize(model):
    from sqlalchemy.orm import class_mapper
    columns = [c.key for c in class_mapper(model.__class__).columns]
    return dict((c, getattr(model, c)) for c in columns)

# 实时查询数据概述
def getData():
    returnData={}
    # 数据概览
    returnData['today_is_traffic_trends'] = today_is_traffic_trends()  # 今日流量趋势
    returnData['visitor_browser_distribution'] = visitor_browser_distribution()  # 访客浏览器分布
    # 新用户增长率
    NOW = datetime.utcnow()
    # 访问率
    all_visted=Log.query.count()
    visted_today_count=Log.query.filter(
        db.cast(Log.createtime, db.DATE) == NOW.date()).count()
    visted_yesterday_count=Log.query.filter(
        db.cast(Log.createtime, db.DATE) == (NOW-timedelta(days=1)).date()).count()
    returnData['new_visted_percent']=round(visted_today_count/all_visted,2)
    # 访问率日同比增长
    returnData['visted_percent']=round(returnData['new_visted_percent']-visted_yesterday_count/all_visted,2)
    return returnData


# 转换为https
def to_https(url):
    return url.replace('http://', 'https://', 1).replace(':443', '')

# redis链接
def redis_connect():
    pool = redis.ConnectionPool(host=Config.CACHE_REDIS_HOST, port=Config.CACHE_REDIS_PORT, db=Config.CACHE_REDIS_DB,password=Config.CACHE_REDIS_PASSWORD)
    r = redis.Redis(connection_pool=pool)
    return r